<?php

namespace App\Service\OpenShop\Feishu;

use App\Enums\BaseErrorCode;
use App\Exceptions\Custom\ResponseHttpException;
use App\Http\Middleware\CallingCards\FeishuAuth;
use App\Http\Middleware\OpenShop\AppletAuth;
use App\Http\Middleware\OpenShop\FeishuWebAuth;
use App\Http\Middleware\OpenShop\UserPermissionAuth;
use App\Models\BaseModel;
use App\Models\Common\ConfigModel;
use App\Models\Common\FsCompanyModel;
use App\Models\Common\FsCompanyRoleMappingModel;
use App\Models\Common\FsCompanyUserModel;
use App\Models\Cruise\CruiseCheckCompanyModel;
use App\Models\Cruise\CruiseCheckDetailModel;
use App\Models\Cruise\CruiseCheckTaskGroupModel;
use App\Models\Cruise\CruiseOrderModel;
use App\Models\Cruise\CruiseTemplateModel;
use App\Models\OpenShop\Common\OpenShopOrderManagerModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopAddressModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopMainProcessModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopOrganizationManageUserModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSignOrderPermissionAnchorModel;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

/**
 * 开店权限类
 */
class PermissionService
{
    public const PERMISSION_ALL                 = 0; // 所有权限
    public const PERMISSION_CITY                = 6; // 城市运营经理权限
    public const PERMISSION_DEVELOP_CITY        = 7; // 城市开发经理权限
    public const PERMISSION_PROVINCE            = 2; // 省总权限
    public const PERMISSION_PERSON              = 1; // 个人权限
    public const PERMISSION_DENY                = -1; // 无权限
    public const PERMISSION_SUPERVISE           = 3; // 营运督导
    public const PERMISSION_CHECK_SUPERVISE     = 4; // 稽核督导
    public const PERMISSION_EXT_CHECK_SUPERVISE = 5; // 第三方品控

    public const PERMISSION_TEXT_MAPPING = [
        self::PERMISSION_ALL                 => '管理员',
        self::PERMISSION_CITY                => '城市运营经理',
        self::PERMISSION_DEVELOP_CITY        => '城市开发经理',
        self::PERMISSION_PROVINCE            => '省区总',
        self::PERMISSION_PERSON              => '开发经理',
        self::PERMISSION_DENY                => '无权限',
        self::PERMISSION_SUPERVISE           => '督导',
        self::PERMISSION_CHECK_SUPERVISE     => '稽核督导',
        self::PERMISSION_EXT_CHECK_SUPERVISE => '第三方品控',
    ];

    // 订单权限
    public const URI_SIGN_ORDER = 'openshop.feishu.signorder.index';
    // 选址待办权限
    public const SITE_LOCATION_PERMISSION = 'openshop.sitelocation.siteform.getsitesurveylist';
    // 夸父增长
    public const CRUISE_CRUISE_LISTS = 'cruise.cruise.lists';
    // 夸父稽核
    public const CRUISE_CHECK_TASK_LISTS = 'cruise.cruise.checklists';

    //更改顾问权限

    public const ORDER_CHANGE_MANAGER_1 = 'openshop.feishu.order.changemanager.one';
    public const ORDER_CHANGE_MANAGER_2 = 'openshop.feishu.order.changemanager.two';
    public const ORDER_CHANGE_MANAGER_3 = 'openshop.feishu.order.changemanager.three';
    public const ORDER_CHANGE_MANAGER_4 = 'openshop.feishu.order.changemanager.four';
    public const ORDER_CHANGE_MANAGER_5 = 'openshop.feishu.order.changemanager.five';


    const ORIGIN_TASK = 1; //代办
    const ORIGIN_SHOP = 2; //门店

    /**
     *
     * 即将废弃，请用PermissionService->getOrderPermissionDataOrder代替 !!!!!!!!!!!
     *
     * @param string $uri
     * @return int
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public static function hasAll(string $uri = ''): int
    {
        $request    = getRequest();
        $action     = $request->route()->action;
        $middleware = isset($action["middleware"]) ? array_values($action["middleware"]) : [];
        if (in_array(FeishuWebAuth::class, $middleware)) {
            $uri            = $uri ?: getControllerUri();
            $permissionList = getRmsUserPermissionList();
            // 判断 是否存在
            if (in_array($uri, $permissionList)) {
                if (in_array($uri . '_all', $permissionList)) {
                    return 0;
                } else {
                    return getRmsUserInfoByAuth()->id;
                }
            } else {
                return -1;
            }
        }
        return 0;
    }


    /**
     * 数据权限判断
     *
     * @param string $uri
     * @return int
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public static function dataPermission(string $uri = '', array $permissionList = [], string $model = UserPermissionAuth::MODULE_OPEN_SHOP): int
    {
//        $request    = getRequest();
//        $action     = $request->route()->action;
//        $middleware = isset($action["middleware"]) ? array_values($action["middleware"]) : [];

//        // 判断是否在校验路由中
//        if (!in_array(FeishuWebAuth::class, $middleware)) {
//            return self::PERMISSION_ALL;
//        }

        $uri            = $uri ?: getControllerUri();
        $permissionList = $permissionList ?: getRmsUserPermissionList([], $model);
        // 判断是否拥有权限
        if (!in_array($uri, $permissionList)) {
            return self::PERMISSION_DENY;
        }

        // 判断是否拥有所有权限
        if (in_array($uri . '_all', $permissionList)) {
            return self::PERMISSION_ALL;
        }

        // 判断是否拥有省区权限
        if (in_array($uri . '_province', $permissionList)) {
            return self::PERMISSION_PROVINCE;
        }

        // 省总用组织架构判断
        $userId = getRmsUserId();
        if ($userId) {
            $areaList = OrganizationManageService::getAreaListByUserId($userId);
            if ($areaList['isAll'] || $areaList['list']) {
                return self::PERMISSION_PROVINCE;
            }
        }


        if ($userId) {
            // todo  判断是否拥有城市开发经理权限
            $checkDevelopCity = OpenShopOrganizationManageUserModel::query()
                                                                   ->where('userId', $userId)
                                                                   ->where('type', OpenShopOrganizationManageUserModel::TYPE_DEVELOP_CITY_MANAGER)
                                                                   ->count();
            if ($checkDevelopCity) {
                return self::PERMISSION_CITY;
            }

            // todo  判断是否拥有城市运营经理权限
            $checkCity = OpenShopOrganizationManageUserModel::query()
                                                            ->where('userId', $userId)
                                                            ->where('type', OpenShopOrganizationManageUserModel::TYPE_CITY_MANAGER)
                                                            ->count();
            if ($checkCity) {
                return self::PERMISSION_CITY;
            }
        }

        // 返回个人权限
        return self::PERMISSION_PERSON;
    }


    //获得可更换顾问的权限列表
    public static function changeManagerList()
    {
        $permissionList = getRmsUserPermissionList();
        $list = [];
        foreach (OpenShopOrderManagerModel::ORDER_CHANGE_MANAGER_MAPPING as $k => $item) {
            foreach ($permissionList as $value) {
                if ($item == $value) {
                    $list[] = $k;
                }
            }
        }
        return $list;
    }


    private Builder $baseQuery;

    /**
     *
     * 根据权限返回数据列表
     *
     * @param $dataPermission
     * @param int $userId
     * @return array
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function getOrderPermissionDataOrder(int $dataPermission, int $userId): array
    {
        $isAll = false;
        $rawSql = '';

        $this->baseQuery = OpenShopSignOrderPermissionAnchorModel::query()
            ->where(function ($query) use ($userId) {
                $query->Where('signInvestmentManagerId', $userId)// 招商经理
                      ->orWhere('localInvestmentManagerId', $userId)// 选址开发
                      ->orWhere('designUid', $userId) // 空间设计师
                      ->orWhere('preparationUid', $userId) // 空间设计筹备确认人
                      ->orWhere('checkManagerId', $userId) // 工程确认人
                      ->orWhere('localInvestmentHandleUserId', $userId) // 经办人
                      ->orWhere('designUidHandleUserId', $userId) // 经办人
                      ->orWhere('checkManagerHandleUserId', $userId); // 经办人
            });
        // 根据订单号去处理
        switch ($dataPermission) {
            case PermissionService::PERMISSION_ALL:
                $isAll = true;
                break;
            case PermissionService::PERMISSION_PROVINCE:
                $areaList = OrganizationManageService::getAreaListByUserId($userId);
                if ($areaList['isAll']) {
                    $isAll = true;
                    break;
                }

                $this->baseQuery = $this->baseQuery
                    ->orWhereIn('provinceCode', $areaList['list'])
                    ->select('orderNo');

                $rawSql = str_replace('?', '%s', $this->baseQuery->toSql());
                $rawSql = sprintf($rawSql, ...$this->baseQuery->getBindings());
                $rawSql = "orderNo in ($rawSql)";

                break;

            case PermissionService::PERMISSION_CITY:
                $cityCodes = [];
                OpenShopOrganizationManageUserModel::query()
                                                   ->where('userId', $userId)
                                                   ->where('type', OpenShopOrganizationManageUserModel::TYPE_CITY_MANAGER)
                                                   ->get()
                                                    ->map(function (OpenShopOrganizationManageUserModel $openShopOrganizationManageUserModel) use (&$cityCodes) {
                                                        $cityCodes = array_merge($cityCodes, array_column($openShopOrganizationManageUserModel->addressCodesArr, 'cityCode'));
                                                    });

                $this->baseQuery = $this->baseQuery
                    ->orWhereIn('cityCode', $cityCodes)
                    ->select('orderNo');

                $rawSql = str_replace('?', '%s', $this->baseQuery->toSql());
                $rawSql = sprintf($rawSql, ...$this->baseQuery->getBindings());
                $rawSql = "orderNo in ($rawSql)";
                break;

            case PermissionService::PERMISSION_DEVELOP_CITY:
                // TODO 城市开发经理 区域权限
                $cityCodes = [];
                OpenShopOrganizationManageUserModel::query()
                                                   ->where('userId', $userId)
                                                   ->where('type', OpenShopOrganizationManageUserModel::TYPE_DEVELOP_CITY_MANAGER)
                                                   ->get()
                                                   ->map(function (OpenShopOrganizationManageUserModel $openShopOrganizationManageUserModel) use (&$cityCodes) {
                                                       $cityCodes = array_merge($cityCodes, array_column($openShopOrganizationManageUserModel->addressCodesArr, 'cityCode'));
                                                   });

                $this->baseQuery = $this->baseQuery
                    ->orWhereIn('cityCode', $cityCodes)
                    ->select('orderNo');

                $rawSql = str_replace('?', '%s', $this->baseQuery->toSql());
                $rawSql = sprintf($rawSql, ...$this->baseQuery->getBindings());
                $rawSql = "orderNo in ($rawSql)";
                break;

            case PermissionService::PERMISSION_PERSON:
                $this->baseQuery = $this->baseQuery->select('orderNo');

                $rawSql = str_replace('?', '%s', $this->baseQuery->toSql());
                $rawSql = sprintf($rawSql, ...$this->baseQuery->getBindings());
                $rawSql = "orderNo in ($rawSql)";

                break;
            case PermissionService::PERMISSION_DENY:
                $this->baseQuery = $this->baseQuery->where('id', 0);
                $rawSql = "id=0";
                break;
        }

        return [
            'isAll'  => $isAll,
            'rawSql' => $rawSql,
        ];
    }

    public function getOrderNoLists(): Collection
    {
        return $this->baseQuery->pluck('orderNo');
    }

    /**
     * 稽核权限判断
     * @param string $uri
     * @param array $permissionList
     * @param string $model
     * @param int $origin
     * @param int $templateType
     * @param string $platformName
     * @return array
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function dataCheckPermission(string $uri = '', array $permissionList = [], string $model = UserPermissionAuth::MODULE_OPEN_SHOP, int $origin = self::ORIGIN_SHOP, int $templateType = CruiseTemplateModel::TYPE_3, string $platformName = ''): array
    {
        $uri            = $uri ?: getControllerUri();
        $permissionList = $permissionList ?: getRmsUserPermissionList([], $model);
//        // 判断是否拥有权限
//        if (!in_array($uri, $permissionList)) {
//            throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null, "无权访问");
//        }

        $userId = getRmsUserId();
        $isAll = false;

        // 作为专项巡检的总部负责人相关逻辑处理
        $companyIds = [];
        $isExtAudit = false;  // 是否有审核权限

        if (in_array($templateType, [CruiseTemplateModel::TYPE_3, CruiseTemplateModel::TYPE_8])) {   //如果是门店稽核  有夸父负责人角色

            // 判断是否为夸父总部负责人（常规 + 专项内部）
            $kuafuManager = ConfigModel::getCruiseCheckAudit('', $templateType);
            if (in_array($userId, $kuafuManager)) {
                return [
                    'isAll'  => true,
                    'rawSql' => '',
                ];
            }

            // 针对每个巡检机构的总部负责人
            $fsCompanyId = FsCompanyRoleMappingModel::query()
                ->where('rmsUserId', $userId)
                ->where('roleId', FsCompanyRoleMappingModel::ROLE_ID_KF_REVIEWER)
                ->pluck('fsCompanyId')
                ->toArray();

            $companyIds = FsCompanyModel::query()
                ->whereIn('id', $fsCompanyId)
                ->pluck('departmentId')
                ->toArray();

            if (count($companyIds)) {
                $isExtAudit = true;
            }
        }

        // 判断是否拥有所有权限
        if (in_array($uri . '_all', $permissionList)) {
            return [
                'isAll'  => true,
                'rawSql' => '',
            ];
        }

        $rawSql = '';

        if (in_array($templateType, [CruiseTemplateModel::TYPE_3, CruiseTemplateModel::TYPE_8])) {   //如果是门店稽核  有夸父负责人角色
            // 省总用组织架构判断
            $areaList = OrganizationManageService::getAreaListByUserId($userId);
            if ($areaList['isAll'] || $areaList['list']) {
                $this->baseQuery = OpenShopAddressModel::query()->whereIn('provinceCode', ($areaList['list'] ?? []))->select('orderNo');
                $rawSql1 = BaseModel::toSqlWithParam($this->baseQuery);
                $rawSql .= " or orderNo in ($rawSql1)";
            }

            $mainProcessQuery = OpenShopMainProcessModel::query()
                ->when(true, function ($query) use ($userId){
                    $child = OpenShopOrderManagerModel::query()
                        ->where('type', OpenShopOrderManagerModel::MANAGER_TYPE_5)
                        ->where('managerUid', $userId)
                        ->select('mainProcessId');
                    $query->whereRaw("pid in (" . BaseModel::toSqlWithParam($child) . ')');
                });
            if ($mainProcessQuery->count()) {
                $this->baseQuery = $mainProcessQuery->select('orderNo');
                $rawSql2 = BaseModel::toSqlWithParam($this->baseQuery);
                $rawSql .= " or orderNo in ($rawSql2)";
            }
        }

        // 城市经理
        $addressCodesArr = [];

        OpenShopOrganizationManageUserModel::query()
            ->where('userId', $userId)
            ->where('type', OpenShopOrganizationManageUserModel::TYPE_CITY_MANAGER)
            ->get()
            ->map(function (OpenShopOrganizationManageUserModel $openShopOrganizationManageUserModel) use (&$addressCodesArr) {
                $addressCodesArr = array_merge($addressCodesArr, array_column($openShopOrganizationManageUserModel->addressCodesArr, 'cityCode'));
            });

        if ($addressCodesArr) {
            $this->baseQuery = OpenShopAddressModel::query()->whereIn('cityCode', $addressCodesArr)->select('orderNo');
            $rawSql1 = BaseModel::toSqlWithParam($this->baseQuery);
            $rawSql .= " or orderNo in ($rawSql1)";
        }

        // 将所有id合并，最后统一where in
        $mergeIds = [];

        //判断是否为稽核督导
        switch ($templateType) {
            case CruiseTemplateModel::TYPE_5:
                $tempIds = CruiseCheckDetailModel::query()
                    ->whereRaw("taskId in (select `taskId` from `cruise_check_task_groups` where `role` = 1 and `userId` = $userId and `shopIds` = '[]')")
                    ->pluck('orderId')
                    ->toArray();

                $mergeIds = array_merge($mergeIds, $tempIds);
                break;
            default:
                $organizationManageUserQuery = OpenShopOrganizationManageUserModel::query()
                    ->where('userId', $userId)
                    ->where('type', OpenShopOrganizationManageUserModel::TYPE_CHECK_MANAGER);

                if ($organizationManageUserQuery->count()) {
                    $lists = [];
                    $organizationManageUserQuery->select( 'addressCodes')
                        ->get()
                        ->each(function ($item) use (&$lists) {
                            $lists = array_merge($lists, $item->addressCodesArr);
                        });
                    $this->baseQuery = OpenShopAddressModel::query()
                        ->whereIn('areaCode', array_column($lists, 'regionCode'))
                        ->select('orderNo');
                    $rawSql3 = BaseModel::toSqlWithParam($this->baseQuery);

                    if ($origin == self::ORIGIN_TASK) {
                        // 稽核督导不能看到三方的专项
                        $bQuery   = CruiseOrderModel::query()
                            ->join('cruise_check_details as detail', 'detail.orderId', '=', 'cruise_order.id')
                            ->where('detail.templateType', $templateType)
                            ->where('companyId', '!=', '')
                            ->where('orderNo', '!=', '')
                            ->select('cruise_order.id');
                        $rawSql31 = BaseModel::toSqlWithParam($bQuery);
                        $rawSql  .= " or (orderNo in ($rawSql3) and id not in ($rawSql31))";
                    }
                    if ($origin == self::ORIGIN_SHOP) {
                        $rawSql  .= " or (orderNo in ($rawSql3))";
                    }
                }
        }

        //判断是否为第三方
        //先得到companyId
        $companyIds = array_values(array_merge(FsCompanyUserModel::getDepartmentIdByRmsUserId($userId)->toArray(), $companyIds));

        $temp       = [''];
        //$isExtAudit = false;   //判断是否为审批人
        $companyIds = array_values(array_diff($companyIds, $temp));
        foreach ($companyIds as $companyId) {
            $extUserIds = ConfigModel::getCruiseCheckAudit($companyId, $templateType);
            if (in_array($userId, $extUserIds)) {
                $isExtAudit = true;
                break;
            }
        }
        $extCheckDetailQuery = CruiseCheckDetailModel::query()
            ->where('templateType', $templateType)
            ->when(!$isExtAudit, function ($query) use ($userId){
                $query->whereIn('dealUid', [0, $userId]);
            })
            ->whereIn('companyId', $companyIds);
            // ->orWhere(function ($q) use ($userId) {
            //     $q->where('dealUid', $userId)->where('isDeleted', 0);
            // });
        if ($extCheckDetailQuery->count()) {
            if ($origin == self::ORIGIN_TASK) {
                $tempIds = $extCheckDetailQuery->pluck('orderId')->toArray();
                $mergeIds = array_merge($mergeIds, $tempIds);
            }
            if ($origin == self::ORIGIN_SHOP) {
                $this->baseQuery = CruiseOrderModel::query()
                    ->whereIn('id', $extCheckDetailQuery->pluck('orderId')->toArray())
                    ->select('orderNo');
                $rawSql4 = BaseModel::toSqlWithParam($this->baseQuery);
                $rawSql .= " or orderNo in ($rawSql4)";
            }
        }

        //如果是工厂联系人看本工厂所有的
        //获得工厂
        $cruiseCheckCompanyIds = CruiseCheckCompanyModel::query()
            ->where('status', CruiseCheckCompanyModel::STATUS_ON)
            ->where('companyManagerId', $userId)
            ->pluck('id')->toArray();
        if ($cruiseCheckCompanyIds) {
            $tempIds = CruiseOrderModel::query()
                                       ->whereIn('cruiseCheckCompanyId', $cruiseCheckCompanyIds)
                                       ->pluck('id')
                                       ->toArray();

            $mergeIds = array_merge($mergeIds, $tempIds);
        }

        // id where in
        if ($mergeIds) {
            $mergeIds = array_values(array_unique($mergeIds));
            $rawSql .= " or id in (" . implode(',', $mergeIds) . ")";
        }

        //返回SQL语句的最终态
        $rawSql = substr($rawSql, 4);

        if (!mb_strlen($rawSql)) {
            $rawSql = 'id = 0';
            //throw new ResponseHttpException(403, null, "您暂无权限,请联系管理员");
        }

        // 返回权限
        return [
            'isAll'  => $isAll,
            'rawSql' => "($rawSql)",
        ];
    }
}
